package info.niwota.group.note;

import info.niwota.group.R;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.util.ArrayList;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.net.Uri;
import android.text.ClipboardManager;

public class GreetingHelper {

	private Activity mContext;

	@SuppressWarnings("unused")
	private GreetingHelper() {
	}

	public GreetingHelper(Activity context) {
		mContext = context;
	}

	public void doLoad() {
		int cnt = 0;
		InputStreamReader fr = null;
		ArrayList<StringBuffer[]> records = new ArrayList<StringBuffer[]>();
		try {
			fr = new InputStreamReader(mContext.getResources().openRawResource(
					R.raw.greetings));

			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(false);
			XmlPullParser xpp = factory.newPullParser();
			xpp.setInput(fr);
			int eventType = xpp.getEventType();
			StringBuffer[] cur = new StringBuffer[5];
			int curIdx = -1;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				// save the previous note data-holder when we end a <note> tag
				if (eventType == XmlPullParser.END_TAG
						&& "note".equals(xpp.getName())) {
					if (cur[0] != null && cur[1] != null && !"".equals(cur[0])
							&& !"".equals(cur[1])) {
						records.add(cur);
					}
					cur = new StringBuffer[5];
					curIdx = -1;
				} else if (eventType == XmlPullParser.START_TAG
						&& "title".equals(xpp.getName())) {
					curIdx = 0;
				} else if (eventType == XmlPullParser.START_TAG
						&& "body".equals(xpp.getName())) {
					curIdx = 1;
				} else if (eventType == XmlPullParser.START_TAG
						&& "attachment".equals(xpp.getName())) {
					curIdx = 2;
				} else if (eventType == XmlPullParser.START_TAG
						&& "created".equals(xpp.getName())) {
					curIdx = 3;
				} else if (eventType == XmlPullParser.START_TAG
						&& "modified".equals(xpp.getName())) {
					curIdx = 4;
				} else if (eventType == XmlPullParser.TEXT && curIdx > -1) {
					if (cur[curIdx] == null) {
						cur[curIdx] = new StringBuffer();
					}
					cur[curIdx].append(xpp.getText());
				}
				eventType = xpp.next();
			}

			// we stored data in a stringbuffer so we can skip empty records;
			// now process the successful records & save to Provider
			Long now = System.currentTimeMillis();
			for (StringBuffer[] record : records) {
				Uri uri = Uri.withAppendedPath(Greeting.Notes.ALL_NOTES_URI,
						record[0].toString());
				ContentValues values = new ContentValues();
				values.put("title", record[0].toString().trim());
				values.put("body", record[1].toString().trim());
				values.put("attachment", record[2].toString().trim());
				values.put("created", parseLong(record[3].toString().trim(),
						now));
				values.put("modified", parseLong(record[4].toString().trim(),
						now));
				if (mContext.getContentResolver().insert(uri, values) != null) {
					cnt++;
				}
			}
		} catch (XmlPullParserException e) {
			showResult(R.string.import_failure_title, mContext.getResources()
					.getString(R.string.import_failure_corrupt, e.getMessage()));
			return;
		} catch (Exception e) {
			showResult(R.string.import_failure_title, mContext.getResources()
					.getString(R.string.import_failure_error, e.getMessage()));
			return;
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (IOException e) {
				}
			}
		}
	}

	public void exportNotes() {
		Cursor c = mContext.managedQuery(Greeting.Notes.ALL_NOTES_URI,
				Greeting.GREETING_EXPORT_PROJECTION, null, null,
				Greeting.Notes.DEFAULT_SORT_ORDER);

		boolean dataAvailable = c.moveToFirst();
		StringBuffer sb = new StringBuffer();
		String title, body, attachment, created, modified;
		int cnt = 0;
		sb.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<notes>");
		while (dataAvailable) {
			title = c.getString(c.getColumnIndexOrThrow("title"));
			body = c.getString(c.getColumnIndexOrThrow("body"));
			attachment = c.getString(c.getColumnIndexOrThrow("attachment"));
			modified = c.getString(c.getColumnIndexOrThrow("modified"));
			created = c.getString(c.getColumnIndexOrThrow("created"));
			//
			if (!"".equals(title) && title != null) {
				sb.append("\n");
				sb.append("<note>\n\t<title><![CDATA[");
				sb.append(title);
				sb.append("]]></title>\n\t<body><![CDATA[");
				sb.append(body);
				sb.append("]]></body>\n\t<attachment><![CDATA[");
				sb.append(attachment);
				sb.append("]]></attachment>\n\t<created>");
				sb.append(created);
				sb.append("</created>\n\t");
				sb.append("<modified>");
				sb.append(modified);
				sb.append("</modified>\n</note>");
				cnt++;
			}
			dataAvailable = c.moveToNext();
		}
		sb.append("\n</notes>\n");
		//
		copyToClipboard(sb);
		//
		showResult(R.string.export_success_title, String.format(mContext
				.getResources().getString(R.string.export_success), cnt));
	}

	private Long parseLong(String s, Long val) {
		try {
			return Long.parseLong(s);
		} catch (Exception e) {
		}
		return val;
	}

	private void showResult(int titleId, String msg) {
		new AlertDialog.Builder(mContext).setCancelable(false).setTitle(
				mContext.getResources().getString(titleId)).setMessage(msg)
				.setPositiveButton(R.string.button_ok,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int which) {
							}
						}).create().show();
	}

	private void copyToClipboard(StringBuffer sb) {
		ClipboardManager cb = (ClipboardManager) mContext
				.getSystemService(Context.CLIPBOARD_SERVICE);
		cb.setText(sb.toString());
	}

	public boolean canImport() {
		ClipboardManager cb = (ClipboardManager) mContext
				.getSystemService(Context.CLIPBOARD_SERVICE);
		boolean has = cb.hasText();
		if (!has) {
			return false;
		}
		String txt = cb.getText().toString();
		// a quick & dirty check
		return (txt.indexOf("<notes>") > 0 && txt.lastIndexOf("</notes>") > 0);
	}

	public void doImport() {
		// get data from clipboard
		ClipboardManager cb = (ClipboardManager) mContext
				.getSystemService(Context.CLIPBOARD_SERVICE);
		boolean has = cb.hasText();
		if (!has) {
			return;
		}
		String txt = cb.getText().toString();
		//
		StringReader fr = new StringReader(txt);
		int cnt = 0;
		ArrayList<StringBuffer[]> records = new ArrayList<StringBuffer[]>();
		try {
			// next, parse that sucker
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			factory.setNamespaceAware(false);
			XmlPullParser xpp = factory.newPullParser();
			xpp.setInput(fr);
			int eventType = xpp.getEventType();
			StringBuffer[] cur = new StringBuffer[5];
			int curIdx = -1;
			while (eventType != XmlPullParser.END_DOCUMENT) {
				// save the previous note data-holder when we end a <note> tag
				if (eventType == XmlPullParser.END_TAG
						&& "note".equals(xpp.getName())) {
					if (cur[0] != null && cur[1] != null && !"".equals(cur[0])
							&& !"".equals(cur[1])) {
						records.add(cur);
					}
					cur = new StringBuffer[5];
					curIdx = -1;
				} else if (eventType == XmlPullParser.START_TAG
						&& "title".equals(xpp.getName())) {
					curIdx = 0;
				} else if (eventType == XmlPullParser.START_TAG
						&& "body".equals(xpp.getName())) {
					curIdx = 1;
				} else if (eventType == XmlPullParser.START_TAG
						&& "attachment".equals(xpp.getName())) {
					curIdx = 2;
				} else if (eventType == XmlPullParser.START_TAG
						&& "created".equals(xpp.getName())) {
					curIdx = 3;
				} else if (eventType == XmlPullParser.START_TAG
						&& "modified".equals(xpp.getName())) {
					curIdx = 4;
				} else if (eventType == XmlPullParser.TEXT && curIdx > -1) {
					if (cur[curIdx] == null) {
						cur[curIdx] = new StringBuffer();
					}
					cur[curIdx].append(xpp.getText());
				}
				eventType = xpp.next();
			}

			//
			for (StringBuffer[] record : records) {
				Uri uri = Uri.withAppendedPath(Greeting.Notes.ALL_NOTES_URI,
						record[0].toString());
				ContentValues values = new ContentValues();
				values.put("title", record[0].toString().trim());
				values.put("body", record[1].toString().trim());
				values.put("attachment", record[2].toString().trim());
				values.put("created", Long.parseLong(record[3].toString()
						.trim()));
				values.put("modified", Long.parseLong(record[4].toString()
						.trim()));
				if (mContext.getContentResolver().insert(uri, values) != null) {
					cnt++;
				}
			}
		} catch (XmlPullParserException e) {
			showResult(R.string.import_failure_title, mContext.getResources()
					.getString(R.string.import_failure_corrupt, e.getMessage()));
			return;
		} catch (IOException e) {
			showResult(R.string.import_failure_title, mContext.getResources()
					.getString(R.string.import_failure_error, e.getMessage()));
			return;
		} finally {
			if (fr != null) {
				try {
					fr.close();
				} catch (Exception e) {
				}
			}
		}
		//
		showResult(R.string.import_success_title, String.format(mContext
				.getResources().getString(R.string.import_success), cnt));

	}

	public void deleteAll() {
		mContext.getContentResolver().delete(Greeting.Notes.ALL_NOTES_URI, null, null);
	}
}
